package edu.study.user.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.github.pagehelper.Page;

import edu.study.api.common.dto.BaseRespDto;
import edu.study.api.common.dto.PageRespDto;
import edu.study.api.common.dto.RespDto;
import edu.study.api.common.enums.BaseResultCodeEnum;
import edu.study.api.common.enums.RoleTypeEnum;
import edu.study.api.common.enums.StatusTypeEnum;
import edu.study.common.util.BeanCopy;
import edu.study.common.util.cache.Cache;
import edu.study.user.api.dto.DepartmentAndSubDto;
import edu.study.user.api.dto.DepartmentDto;
import edu.study.user.api.dto.UserDetailDto;
import edu.study.user.api.req.department.AddDepartmentReq;
import edu.study.user.api.req.department.DeleteDepartmentReq;
import edu.study.user.api.req.department.ModifyDepartmentReq;
import edu.study.user.api.req.department.ModifyDepartmentStatusReq;
import edu.study.user.api.req.department.QueryDepartmentPageListReq;
import edu.study.user.api.req.department.QueryDepartmentReq;
import edu.study.user.dao.mapperExt.DepartmentDOMapperExt;
import edu.study.user.dao.mapperExt.DomainDOMapperExt;
import edu.study.user.dbBean.DepartmentDO;
import edu.study.user.dbBean.DomainDO;
import edu.study.user.util.UserUtils;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class DepartmentService {

	@Autowired
	private DepartmentDOMapperExt departmentDOMapperExt;
	
	@Autowired
	private DomainDOMapperExt domainDOMapperExt;

	@Autowired
	private Cache cache;

	public BaseRespDto addDepartment(AddDepartmentReq req) {
		BaseRespDto resp = new BaseRespDto();
		
		DomainDO domainDO = domainDOMapperExt.queryByDomainNo(req.getDomainNo());
		if(domainDO == null) {
			log.info("DepartmentService.addDepartment, 租户不存在! domainNo={}", req.getDomainNo());
			resp.setResultFail(BaseResultCodeEnum.RECORD_NOT_FOUND);
			return resp;
		}
		
		if(!StringUtils.isEmpty(req.getParentDepartmentNo()) && !RoleTypeEnum.ROOT.getCode().equals(req.getParentDepartmentNo())){
			DepartmentDO checkDepartmentDO = departmentDOMapperExt.queryByDepartmentNo(req.getParentDepartmentNo());
			if(checkDepartmentDO == null) {
				log.info("DepartmentService.addDepartment, 父部门不存在! departmentNo={}", req.getParentDepartmentNo());
				resp.setResultFail(BaseResultCodeEnum.RECORD_NOT_FOUND);
				return resp;
			}
			checkDepartmentDO = departmentDOMapperExt.queryDepartmentForCheck(req.getParentDepartmentNo(), req.getDepartmentName(), null);
			if (checkDepartmentDO != null) {
				log.info("DepartmentService.addDepartment, 同一个父部门下面的子部门不允许名称一样! parentDepartmentNo={}, departmentName={}", req.getParentDepartmentNo(), req.getDepartmentName());
				resp.setResultFail(BaseResultCodeEnum.RECORD_ALREADY_EXISTS);
				return resp;
			}
		}
		if(StringUtils.isEmpty(req.getParentDepartmentNo()) || RoleTypeEnum.ROOT.getCode().equals(req.getParentDepartmentNo())){
			DepartmentDO checkDepartmentDO = departmentDOMapperExt.queryDepartmentForCheck(RoleTypeEnum.ROOT.getCode(), req.getDepartmentName(), req.getDomainNo());
			if (checkDepartmentDO != null) {
				log.info("DepartmentService.addDepartment, 同一个租户下面的一级部门不允许名称一样! domainNo={}, departmentName={}", req.getDomainNo(), req.getDepartmentName());
				resp.setResultFail(BaseResultCodeEnum.RECORD_ALREADY_EXISTS);
				return resp;
			}
		}
		DepartmentDO newDepartmentDO = new DepartmentDO();
		BeanCopy.copyFromSrcToDest(req, newDepartmentDO);
		String departmentNo = cache.generateStr("departmentNo_", 1, null);
		newDepartmentDO.setDepartmentNo(departmentNo);
		UserDetailDto userDetailDto = UserUtils.getCurrentUser();
		if(userDetailDto!=null) {
			newDepartmentDO.setCreator(userDetailDto.getLoginName());
			newDepartmentDO.setModifier(userDetailDto.getLoginName());
		}
		int i = departmentDOMapperExt.insertSelective(newDepartmentDO);
		if (i == 0) {
			resp.setResultFail(BaseResultCodeEnum.DB_ERROR);
			return resp;
		}
		return resp;
	}

	public BaseRespDto deleteDepartment(DeleteDepartmentReq req) {
		BaseRespDto resp = new BaseRespDto();

		DepartmentDO departmentDO = departmentDOMapperExt.queryByDepartmentNo(req.getDepartmentNo());
		if (departmentDO == null) {
			resp.setResultFail(BaseResultCodeEnum.RECORD_NOT_FOUND);
			return resp;
		}
		//todo 删除了，关联的数据怎么处理？？？
		DepartmentDO newDepartmentDO = new DepartmentDO();
		newDepartmentDO.setId(departmentDO.getId());
		newDepartmentDO.setIsDeleted(StatusTypeEnum.Y.getCode());
		int i = departmentDOMapperExt.updateByPrimaryKeySelective(newDepartmentDO);
		if (i == 0) {
			resp.setResultFail(BaseResultCodeEnum.DB_ERROR);
			return resp;
		}
		return resp;
	}
	
	public BaseRespDto modifyDepartment(ModifyDepartmentReq req) {
		BaseRespDto resp = new BaseRespDto();

		DepartmentDO departmentDO = departmentDOMapperExt.queryByDepartmentNo(req.getDepartmentNo());
		if (departmentDO == null) {
			resp.setResultFail(BaseResultCodeEnum.RECORD_NOT_FOUND);
			return resp;
		}
		
		//校验有没有修改部门名称
		if(!StringUtils.isEmpty(req.getDepartmentName()) && !departmentDO.getDepartmentName().equals(req.getDepartmentName())) {
			if(!StringUtils.isEmpty(departmentDO.getParentDepartmentNo()) && !RoleTypeEnum.ROOT.getCode().equals(departmentDO.getParentDepartmentNo())){
				DepartmentDO checkDepartmentDO = departmentDOMapperExt.queryDepartmentForCheck(departmentDO.getParentDepartmentNo(), req.getDepartmentName(), null);
				if (checkDepartmentDO != null && !checkDepartmentDO.getDepartmentNo().equals(req.getDepartmentNo())) {
					log.info("DepartmentService.modifyDepartment, 同一个父部门下面的子部门不允许名称一样! parentDepartmentNo={}, departmentName={}", departmentDO.getParentDepartmentNo(), req.getDepartmentName());
					resp.setResultFail(BaseResultCodeEnum.RECORD_ALREADY_EXISTS);
					return resp;
				}
			}
			if(StringUtils.isEmpty(departmentDO.getParentDepartmentNo()) || RoleTypeEnum.ROOT.getCode().equals(departmentDO.getParentDepartmentNo())){
				DepartmentDO checkDepartmentDO = departmentDOMapperExt.queryDepartmentForCheck(RoleTypeEnum.ROOT.getCode(), req.getDepartmentName(), departmentDO.getDomainNo());
				if (checkDepartmentDO != null) {
					log.info("DepartmentService.modifyDepartment, 同一个租户下面的一级部门不允许名称一样! domainNo={}, departmentName={}", checkDepartmentDO.getDomainNo(), req.getDepartmentName());
					resp.setResultFail(BaseResultCodeEnum.RECORD_ALREADY_EXISTS);
					return resp;
				}
			}
		}
		
		DepartmentDO newDepartmentDO = new DepartmentDO();
		BeanCopy.copyFromSrcToDest(req, newDepartmentDO);
		newDepartmentDO.setDepartmentNo(null);
		newDepartmentDO.setId(departmentDO.getId());
		UserDetailDto userDetailDto = UserUtils.getCurrentUser();
		if(userDetailDto!=null) {
			newDepartmentDO.setModifier(userDetailDto.getLoginName());
		}
		int i = departmentDOMapperExt.updateByPrimaryKeySelective(newDepartmentDO);
		if (i == 0) {
			resp.setResultFail(BaseResultCodeEnum.DB_ERROR);
			return resp;
		}
		return resp;
	}
	
	public BaseRespDto modifyDepartmentStatus(ModifyDepartmentStatusReq req) {
		BaseRespDto resp = new BaseRespDto();

		DepartmentDO departmentDO = departmentDOMapperExt.queryByDepartmentNo(req.getDepartmentNo());
		if (departmentDO == null) {
			resp.setResultFail(BaseResultCodeEnum.RECORD_NOT_FOUND);
			return resp;
		}
		if(req.getStatus().equals(departmentDO.getStatus())) {
			log.info("DepartmentService.modifyDepartmentStatus, 不用修改, departmentNo={}", req.getDepartmentNo());
			return resp;
		}
		//todo 失效了，关联的数据怎么处理？？？
		DepartmentDO newDepartmentDO = new DepartmentDO();
		newDepartmentDO.setId(departmentDO.getId());
		newDepartmentDO.setStatus(req.getStatus());
		UserDetailDto userDetailDto = UserUtils.getCurrentUser();
		if(userDetailDto!=null){
			newDepartmentDO.setModifier(userDetailDto.getLoginName());
		}
		int i = departmentDOMapperExt.updateByPrimaryKeySelective(newDepartmentDO);
		if (i == 0) {
			resp.setResultFail(BaseResultCodeEnum.DB_ERROR);
			return resp;
		}
		return resp;
	}
	
	public RespDto<DepartmentDto> queryDepartment(QueryDepartmentReq req) {
		RespDto<DepartmentDto> resp = new RespDto<DepartmentDto>();

		DepartmentDO departmentDO = departmentDOMapperExt.queryByDepartmentNo(req.getDepartmentNo());
		if (departmentDO == null) {
			resp.setResultFail(BaseResultCodeEnum.RECORD_NOT_FOUND);
			return resp;
		}
		DepartmentDto departmentDto = new DepartmentDto();
		BeanCopy.copyFromSrcToDest(departmentDO, departmentDto);
		resp.setData(departmentDto);
		return resp;
	}
		
	public PageRespDto<DepartmentAndSubDto> queryDepartmentPageList(QueryDepartmentPageListReq req) {
		PageRespDto<DepartmentAndSubDto> resp = new PageRespDto<DepartmentAndSubDto>();
		if(StringUtils.isEmpty(req.getParentDepartmentNo())) {
			req.setParentDepartmentNo(RoleTypeEnum.ROOT.getCode());//默认从一级部门查起
		}
		
		Page<DepartmentDto> departmentDtoPageList = departmentDOMapperExt.queryDepartmentPageList(req);
		if (departmentDtoPageList != null && !CollectionUtils.isEmpty(departmentDtoPageList.getResult())) {
			resp.setPages(departmentDtoPageList.getPages());
			resp.setTotal(departmentDtoPageList.getTotal());
			//resp.setData(departmentDtoPageList.getResult());
			
			List<DepartmentAndSubDto> departmentAndSubDtoList = new ArrayList<DepartmentAndSubDto>();
			for (DepartmentDto departmentDto : departmentDtoPageList) {
				QueryDepartmentReq queryDepartmentReq = new QueryDepartmentReq();
				queryDepartmentReq.setDepartmentNo(departmentDto.getDepartmentNo());
				RespDto<DepartmentAndSubDto> departmentAndSubDto = queryDepartmentAndSub(queryDepartmentReq);
				departmentAndSubDtoList.add(departmentAndSubDto.getData());
			}
			resp.setData(departmentAndSubDtoList);
		}
		return resp;
	}
	
	public RespDto<List<DepartmentDto>> queryDepartmentAndSubList(QueryDepartmentReq req) {
		RespDto<List<DepartmentDto>> resp = new RespDto<List<DepartmentDto>>();
		
		DepartmentDO departmentDO = departmentDOMapperExt.queryByDepartmentNo(req.getDepartmentNo());
		if (departmentDO == null) {
			resp.setResultFail(BaseResultCodeEnum.RECORD_NOT_FOUND);
			return resp;
		}
		List<DepartmentDto> departmentDtoList = new ArrayList<DepartmentDto>();
		DepartmentDto departmentDto = new DepartmentDto();
		BeanCopy.copyFromSrcToDest(departmentDO, departmentDto);
		departmentDtoList.add(departmentDto);
		
		this.querySubDepartmentList(departmentDto, departmentDtoList);
		
		resp.setData(departmentDtoList);		
		return resp;
	}
	
	private void querySubDepartmentList(DepartmentDto departmentDto, List<DepartmentDto> departmentDtoListAll) {
		List<DepartmentDto> departmentDtoList = departmentDOMapperExt.queryByParentDepartmentNo(departmentDto.getDepartmentNo());
		if (!CollectionUtils.isEmpty(departmentDtoList)) {
			departmentDtoListAll.addAll(departmentDtoList);
			for (DepartmentDto item : departmentDtoList) {
				this.querySubDepartmentList(item, departmentDtoListAll);
			}
		}
	}
	
	public RespDto<DepartmentAndSubDto> queryDepartmentAndSub(QueryDepartmentReq req) {
		RespDto<DepartmentAndSubDto> resp = new RespDto<DepartmentAndSubDto>();
		
		DepartmentDO departmentDO = departmentDOMapperExt.queryByDepartmentNo(req.getDepartmentNo());
		if (departmentDO == null) {
			resp.setResultFail(BaseResultCodeEnum.RECORD_NOT_FOUND);
			return resp;
		}
		
		DepartmentAndSubDto departmentAndSubDto = new DepartmentAndSubDto();
		BeanCopy.copyFromSrcToDest(departmentDO, departmentAndSubDto);
		
		departmentAndSubDto = this.querySubDepartment(departmentAndSubDto);
		
		resp.setData(departmentAndSubDto);
		return resp;
	}
	
	public DepartmentAndSubDto querySubDepartment(DepartmentAndSubDto departmentAndSubDto) {
		List<DepartmentDto> departmentDtoList = departmentDOMapperExt.queryByParentDepartmentNo(departmentAndSubDto.getDepartmentNo());
		if (!CollectionUtils.isEmpty(departmentDtoList)) {
			List<DepartmentAndSubDto> subDepartmentList = new ArrayList<DepartmentAndSubDto>();
			for (DepartmentDto item : departmentDtoList) {
				DepartmentAndSubDto subDepartment = new DepartmentAndSubDto();
				BeanCopy.copyFromSrcToDest(item, subDepartment);
				subDepartment = querySubDepartment(subDepartment);
				subDepartmentList.add(subDepartment);
			}
			departmentAndSubDto.setSubDepartmentList(subDepartmentList);
		}
		return departmentAndSubDto;
	}
}
